/* This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */
package l1j.server.server.types;

public class Point {
	protected int _x = 0;
	protected int _y = 0;

	public Point() {
	}

	public Point(int x, int y) {
		_x = x;
		_y = y;
	}

	public Point(Point pt) {
		_x = pt._x;
		_y = pt._y;
	}

	public int getX() {
		return _x;
	}

	public void setX(int x) {
		_x = x;
	}

	public int getY() {
		return _y;
	}

	public void setY(int y) {
		_y = y;
	}

	public void set(Point pt) {
		_x = pt._x;
		_y = pt._y;
	}

	public void set(int x, int y) {
		_x = x;
		_y = y;
	}

	/**
	 * 指定された座標への直線距離を返す。
	 * 
	 * @param pt
	 *            座標を保持するPointオブジェクト
	 * @return 座標までの直線距離
	 */
	public double getLineDistance(Point pt) {
		long diffX = pt.getX() - this.getX();
		long diffY = pt.getY() - this.getY();
		return Math.sqrt((diffX * diffX) + (diffY * diffY));
	}

	/**
	 * 指定された座標までの直線タイル数を返す。
	 * 
	 * @param pt
	 *            座標を保持するPointオブジェクト
	 * @return 指定された座標までの直線タイル数。
	 */
	public int getTileLineDistance(Point pt) {
		return Math.max(Math.abs(pt.getX() - getX()), Math.abs(pt.getY()
				- getY()));
	}

	/**
	 * 指定された座標までのタイル数を返す。
	 * 
	 * @param pt
	 *            座標を保持するPointオブジェクト
	 * @return 指定された座標までのタイル数。
	 */
	public int getTileDistance(Point pt) {
		return Math.abs(pt.getX() - getX()) + Math.abs(pt.getY() - getY());
	}

	/**
	 * 指定されたオブジェクトが画面内に見えるかを返す
	 * 
	 * プレイヤーの座標を(0,0)とすれば見える範囲の座標は
	 * 
	 * 左上(2,-15)右上(15,-2)左下(-15,2)右下(-2,15)となる。
	 * 
	 * @param pt
	 *            座標を保持するPointオブジェクト
	 * @return 指定されたオブジェクトが画面内に見えるか否か。
	 */
	public boolean isInScreen(Point pt) {
		long diffX = pt.getX() - this.getX();
		long diffY = pt.getY() - this.getY();

		// 遠すぎる場合
		if (diffX > 15 || diffX < -15 || diffY > 15 || diffY < -15) {
			return false;
		}

		int locX = 2; // 左上のX座標の差
		int locY = -15; // 左上のY座標の差
		// 左端から右端へ座標をチェックし、右端に達すれば一段下げてまた左端から右端へ
		for (int x1 = locX, y1 = locY; x1 >= locX - 17 && y1 <= locY + 17;
				x1--, y1++) {
			for (int x2 = x1, y2 = y1; x2 <= x1 + 13 && y2 <= y1 + 13;
					x2++, y2++) {
				if (diffX == x2 && diffY == y2) {
					return true;
				}
			}
		}

		// X軸Y軸が斜め方向になっているため、上記チェックだけでは間のマスが漏れる
		locX = 2;
		locY = -14;
		for (int x1 = locX, y1 = locY; x1 >= locX - 16 && y1 <= locY + 16;
				x1--, y1++) {
			for (int x2 = x1, y2 = y1; x2 <= x1 + 12 && y2 <= y1 + 12;
					x2++, y2++) {
				if (diffX == x2 && diffY == y2) {
					return true;
				}
			}
		}

		return false;
	}

	@Override
	public Point clone() {
		return new Point(this);
	}

	@Override
	public int hashCode() {
		return 7 * getX() + getY();
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof Point)) {
			return false;
		}
		Point pt = (Point) obj;
		return (this.getX() == pt.getX()) && (this.getY() == pt.getY());
	}
}
